using Luban.DataExporter.Builtin.Json;
using Luban.Datas;
using Luban.Types;
using Luban.TypeVisitors;

namespace Luban.Typescript.TypeVisitors;

public class JsonUnderlyingDeserializeVisitor : ITypeFuncVisitor<string, string, int, string>
{
    public static JsonUnderlyingDeserializeVisitor Ins { get; } = new JsonUnderlyingDeserializeVisitor();

    public string Accept(TBool type, string jsonVarName, string fieldName, int depth)
    {
        return $"{fieldName} = {jsonVarName}";
    }

    public string Accept(TByte type, string jsonVarName, string fieldName, int depth)
    {
        return $"{fieldName} = {jsonVarName}";
    }

    public string Accept(TShort type, string jsonVarName, string fieldName, int depth)
    {
        return $"{fieldName} = {jsonVarName}";
    }

    public string Accept(TInt type, string jsonVarName, string fieldName, int depth)
    {
        return $"{fieldName} = {jsonVarName}";
    }

    public string Accept(TLong type, string jsonVarName, string fieldName, int depth)
    {
        return $"{fieldName} = {jsonVarName}";
    }

    public string Accept(TFloat type, string jsonVarName, string fieldName, int depth)
    {
        return $"{fieldName} = {jsonVarName}";
    }

    public string Accept(TDouble type, string jsonVarName, string fieldName, int depth)
    {
        return $"{fieldName} = {jsonVarName}";
    }

    public string Accept(TEnum type, string jsonVarName, string fieldName, int depth)
    {
        return $"{fieldName} = {jsonVarName}";
    }

    public string Accept(TString type, string jsonVarName, string fieldName, int depth)
    {
        return $"{fieldName} = {jsonVarName}";
    }

    public string Accept(TDateTime type, string jsonVarName, string fieldName, int depth)
    {
        return $"{fieldName} = {jsonVarName}";
    }

    public string Accept(TBean type, string jsonVarName, string fieldName, int depth)
    {
        if (type.DefBean.IsAbstractType)
        {
            return $"{fieldName} = {type.DefBean.FullName}.constructorFrom({jsonVarName})";
        }
        else
        {
            return $"{fieldName} = new {type.DefBean.FullName}({jsonVarName})";
        }
    }

    public string Accept(TArray type, string jsonVarName, string fieldName, int depth)
    {
        return $"{fieldName} = [];\n    for (const _ele{depth} of {jsonVarName}) {{\n      const {type.ElementType.Apply(this, $"_ele{depth}", $"_e{depth}", depth + 1)};\n      {fieldName}.push(_e{depth});\n    }}";
    }

    public string Accept(TList type, string jsonVarName, string fieldName, int depth)
    {
        return $"{fieldName} = [];\n    for (const _ele{depth} of {jsonVarName}) {{\n      const {type.ElementType.Apply(this, $"_ele{depth}", $"_e{depth}", depth + 1)};\n      {fieldName}.push(_e{depth});\n    }}";
    }

    public string Accept(TSet type, string jsonVarName, string fieldName, int depth)
    {
        if (type.ElementType.Apply(SimpleJsonTypeVisitor.Ins))
        {
            return $"{fieldName} = {jsonVarName}";
        }
        else
        {
            return $"{fieldName} = new {type.Apply(DeclaringTypeNameVisitor.Ins)}();\n    for (const _ele{depth} of {jsonVarName}) {{\n      const {type.ElementType.Apply(this, $"_ele{depth}", $"_e{depth}", depth + 1)};\n      {fieldName}.add(_e{depth});\n    }}";
        }
    }

    public string Accept(TMap type, string jsonVarName, string fieldName, int depth)
    {
        return $"{fieldName} = new {type.Apply(DeclaringTypeNameVisitor.Ins)}();\n    for (const _entry{depth}_ of {jsonVarName}) {{\n      const {type.KeyType.Apply(this, $"_entry{depth}_[0]", $"_k{depth}", depth + 1)};\n      const {type.ValueType.Apply(this, $"_entry{depth}_[1]", $"_v{depth}", depth + 1)};\n      {fieldName}.set(_k{depth}, _v{depth});\n    }}";
    }
}
